package org.i9.slb.platform.anseko.hypervisors.kvm;

import org.i9.slb.platform.anseko.hypervisors.kvm.hypervisors.LibvirtVMDef;
import org.i9.slb.platform.anseko.hypervisors.AbstractSimulatorBuilder;
import org.i9.slb.platform.anseko.hypervisors.param.SimulatorDisk;
import org.i9.slb.platform.anseko.hypervisors.param.SimulatorInfo;
import org.i9.slb.platform.anseko.hypervisors.param.SimulatorNetwork;
import org.i9.slb.platform.anseko.hypervisors.param.SimulatorViewer;

import java.util.ArrayList;
import java.util.List;

/**
 * kvm虚拟化构建器
 *
 * @author R12
 * @version 1.0
 * @date 2018/8/30 11:04
 */
public class KVMSimulatorBuilder extends AbstractSimulatorBuilder {

    public KVMSimulatorBuilder(SimulatorInfo simulatorInfo) {
        super(simulatorInfo);
    }

    @Override
    protected String makeDefineSimulatorFile(SimulatorInfo simulatorInfo) {
        LibvirtVMDef libvirtVMDef = createLibvirtVMDef();
        LibvirtVMDef.DevicesDef devicesDef = createDevicesDef();
        libvirtVMDef.addComp(devicesDef);
        return libvirtVMDef.toString();
    }

    private LibvirtVMDef createLibvirtVMDef() {
        LibvirtVMDef libvirtVM = new LibvirtVMDef();

        //根据物理机来取得虚拟化类型
        libvirtVM.setHvsType("kvm");
        libvirtVM.setDomainName(this.simulatorInfo.getName());
        libvirtVM.setDomUUID(this.simulatorInfo.getUuid());
        libvirtVM.setDomDescription("android虚拟机");

        LibvirtVMDef.GuestDef guestDef = new LibvirtVMDef.GuestDef();
        guestDef.setGuestType(LibvirtVMDef.GuestDef.GuestType.KVM);
        guestDef.setGuestArch("x86_64");
        guestDef.setMachineType("rhel6.6.0");
        guestDef.setBootOrder(LibvirtVMDef.GuestDef.BootOrder.HARDISK);
        libvirtVM.addComp(guestDef);

        LibvirtVMDef.GuestResourceDef guestResource = new LibvirtVMDef.GuestResourceDef();

        guestResource.setMemorySize(this.simulatorInfo.getMemoryKB());
        guestResource.setVcpuNum(this.simulatorInfo.getCpunum());
        libvirtVM.addComp(guestResource);

        LibvirtVMDef.FeaturesDef featuresDef = new LibvirtVMDef.FeaturesDef();
        featuresDef.addFeatures("pae");
        featuresDef.addFeatures("apic");
        featuresDef.addFeatures("acpi");
        libvirtVM.addComp(featuresDef);

        LibvirtVMDef.TermPolicy termPolicy = new LibvirtVMDef.TermPolicy();
        termPolicy.setCrashPolicy("destroy");
        termPolicy.setPowerOffPolicy("destroy");
        termPolicy.setRebootPolicy("restart");
        libvirtVM.addComp(termPolicy);

        return libvirtVM;
    }

    /**
     * 创建虚拟机上的硬件设备
     *
     * @return
     */
    private LibvirtVMDef.DevicesDef createDevicesDef() {
        LibvirtVMDef.DevicesDef devicesDef = new LibvirtVMDef.DevicesDef();
        //设置模拟器类型
        devicesDef.setEmulatorPath("/usr/libexec/qemu-kvm");

        //磁盘管理
        int index = 0;
        for (SimulatorDisk simulatorDisk : this.simulatorInfo.getSimulatorDisks()) {
            LibvirtVMDef.DiskDef diskDef = createDiskDef(simulatorDisk, index);
            devicesDef.addDevice(diskDef);
            index++;
        }

        //网卡管理
        for (LibvirtVMDef.InterfaceDef interfaceDef : createInterfaceDef()) {
            devicesDef.addDevice(interfaceDef);
        }

        //定义其它辅助设备
        for (Object object : createOtherDevice()) {
            devicesDef.addDevice(object);
        }

        return devicesDef;
    }

    private List<Object> createOtherDevice() {
        List<Object> result = new ArrayList<Object>();
        result.add(new LibvirtVMDef.SerialDef("pty", null, (short) 0));
        result.add(new LibvirtVMDef.ConsoleDef("pty", null, null, (short) 0));

        //定义vnc控制
        SimulatorViewer simulatorViewer = this.simulatorInfo.getSimulatorViewer();
        result.add(new LibvirtVMDef.GraphicDef("vnc",
                (short) simulatorViewer.getPort(), false, "0.0.0.0", simulatorViewer.getPassword(), null));

        //定义输入设备
        result.add(new LibvirtVMDef.InputDef("tablet", "usb"));

        //定义显示设备
        result.add(new LibvirtVMDef.VideoDef("vga"));

        return result;
    }

    /**
     * 网卡管理
     *
     * @return
     */
    private List<LibvirtVMDef.InterfaceDef> createInterfaceDef() {
        //设置多块网卡
        List<LibvirtVMDef.InterfaceDef> interfaceDefs = new ArrayList<LibvirtVMDef.InterfaceDef>();
        for (SimulatorNetwork simulatorNetwork : this.simulatorInfo.getSimulatorNetworks()) {
            LibvirtVMDef.InterfaceDef nic = new LibvirtVMDef.InterfaceDef();
            //获取虚拟机限速大小kb
            final int networkRateKBps = simulatorNetwork.getNetworkRateKBps();
            //不要给网卡model值android系统连接不上网
            nic.defPrivateNet("default", simulatorNetwork.getTargetName(),
                    simulatorNetwork.getMac(), null, networkRateKBps);
            interfaceDefs.add(nic);
        }
        return interfaceDefs;
    }

    /**
     * 创建一个指定类型的磁盘
     *
     * @param simulatorDisk
     * @param index
     * @return
     */
    private LibvirtVMDef.DiskDef createDiskDef(SimulatorDisk simulatorDisk, int index) {
        LibvirtVMDef.DiskDef diskDef = new LibvirtVMDef.DiskDef();
        String diskPath = simulatorDisk.getDiskPath();
        diskDef.defBlockBasedDisk(diskPath, index,
                LibvirtVMDef.DiskDef.DiskBus.VIRTIO, LibvirtVMDef.GuestDef.GuestType.KVM);
        return diskDef;
    }
}
